<style scoped>
</style>
<template>
  <component class="page-block" v-if="show" :is="type" v-bind="thisProps"></component>
</template>

<script>
import S94Compute from "@/js/S94Compute.js";
import {json_decode_object, to_string} from "@/js/s94_tool.js";
import {componentMap, defineAsyncComponentMap} from "@/components/auto_import/auto_import_tool.js";

/**
 * 获取页面板块组件配置
 * @returns {Promise<{[componentName: string]:{name,title,tip,head_img,has_children,prop_map:{[propName: string]:{name,label,default,tip,type,input_type,is_required,is_boolean}}}}>}
 */
export async function getComponentConfigMap(){
  let map = await componentMap('PageBlock');
  let config = {};
  Object.keys(map).forEach(k=>{
    let row = map[k];
    let prop_map = {};
    Object.keys(row.props).forEach(k2=>{
      let prop = row.props[k2];
      if (/^_.+_$/.test(k2) || !prop._label_) return;
      let types = Array.isArray(prop.type) ? prop.type : [prop.type];
      let type = 'string';
      if (!types.includes(String)){
        if (types.includes(Boolean)) {
          type = 'boolean';
        }else if (types.includes(Array)) {
          type = 'array';
        }else if (types.includes(Object)) {
          type = 'object';
        }
      }
      prop_map[k2] = {
        name: k2,
        label: prop._label_,
        default: prop._default_ || prop.default,
        tip: prop._tip_,
        type: type,
        input_type: prop._input_type_,
        is_required: prop._required_,
        is_boolean: prop.type === Boolean,
      }
    })
    config[k] = {
      name: k,
      title: row._title_,
      tip: row._tip_,
      head_img: row._head_img_,
      group: row._group_,
      prop_map: prop_map,
      has_children: '_children_' in row.props,
    }
  })
  getComponentConfigMap._cache_ = config;
  return config;
}


/**统一的页面板块对外中间件
 * @prop {String} type 类型，对应组件名
 * @prop {*} info 参数解析的info，以_info_参数名，通过props中加入传递给组件
 * @prop {Object} props 组件的props参数，支持计算解析
 * @prop {{type:string, props:Object, children?:Array}[]} children 子板块，以_children_参数名，通过props中加入传递给组件，组件内部解析，
 */
export default {
  props: {
    type: String,
    info: [Array, Object],
    props: Object,
    children: [Array, Object],
  },
  components: defineAsyncComponentMap('PageBlock'),
  data(){
    return {
      show: false,
      configMap: {},
    }
  },
  computed:{
    thisProps(){
      let config = this.configMap[this.type];
      if (!config) return {};
      let prop_map = config.prop_map;
      let props = {};
      if (this.props && typeof this.props === 'object'){
        props = Object.assign(props, this.props);
      }
      let s94Compute = new S94Compute(this.info);
      Object.keys(props).forEach((key) => {
        let val = props[key];
        if (typeof val === 'string') {
          if (/^(\[[\s\S]*\])|(\{[\s\S]*\})$/.test(val)) {
            val = json_decode_object(val);
          }else {
            val = s94Compute.display(val);
          }
        }
        if (prop_map[key]?.is_boolean){
          val = !!val;
        }
        props[key] = val;
      })
      if (this.children && typeof this.children === 'object'){
        props._children_ = [];
        Object.values(this.children).forEach((child)=>{
          if (child.type && child.props) props._children_.push(child);
        })
      }
      props._info_ = this.info;
      //通用的样式参数处理，px转rem
      if (props.style){
        props.style = to_string(props.style).replace(/([\d\.]+)px/g, (p0,p1)=>{
          return isNaN(p1) ? p0 : (p1/100)+'rem';
        })
      }

      return props;
    }
  },
  mounted(){
    getComponentConfigMap().then((config)=>{
      this.configMap = config;
      this.show = true;
    })
  },
  unmounted() {
  }
}
</script>